package com.kaifamiao.month04.day11;

/**
 * java 标识符命名工具类
 * java 标识符可以由 字母、数字、下划线(_)、美元符号($)以及中文组成
 * 注：可以在实现中暂时忽略中文的判断
 */
public class IdentifiersUtil {

    private final String[] keywords = {
            "_", "abstract", "assert", "boolean", "break",
            "byte", "case", "catch", "char", "class",
            "const", "continue", "default", "do", "double",
            "else", "enum", "extends", "final", "finally",
            "float", "for", "goto", "if", "implements",
            "import", "instanceof", "int", "interface", "long",
            "native", "new", "package", "private", "protected",
            "public", "return", "short", "static", "strictfp",
            "super", "switch", "synchronized", "this", "throw",
            "throws", "transient", "try", "void", "volatile",
            "while", "true", "false", "null"
    };

    /**
     * 判断是否是关键字
     * @param str 需要判断的字符串
     * @return 是否存在关键字数组中
     */
    private boolean isExist(String str) {
        for (String s : keywords) {
            if (str.equals(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断 str 是否符合 java 标识符命名
     * @param str 要判断的字符串
     * @return true 表示符合标识符规范，false 表示不符合
     */
    public boolean isJavaIdentifier(String str) {
        if (!isExist(str)) { // 不可以是关键字
            if (Character.toString(str.charAt(0)).matches("[0-9]+")) { // 首字母不可以是数字
                return false;
            } else { // 标识符可以由 字母、数字、下划线(_)、美元符号($)以及中文组成
                for (int i = 0; i < str.length(); i++) {
                    String current = Character.toString(str.charAt(i));
                    if ((!current.matches("[0-9]+") && !current.matches("\\w+") &&
                            !current.matches("[_]+") && !current.matches("[$]+"))) {
                        return false;
                    }
                }
                return true;
            }
        } else {
            return false;
        }
    }

    /**
     * 判断 name 是否符合 类/接口/枚举 命名规范
     * 类/接口/枚举 命名规范指 帕斯卡命名法。
     * 帕斯卡命名法指当名称是由二个或二个以上单词连结在一起，每个单词首字母大写
     * @param name 需要判断的名称
     * @return 是否符合帕斯卡命名规范
     */
    public boolean isPascal(String name) {
        if (isJavaIdentifier(name)) {
            return name.charAt(0) >= 'A' && name.charAt(0) <= 'Z';
        } else {
            return false;
        }
    }

    /**
     * 判断 name 是否符合 变量/方法 命名规范
     * 变量/方法 命名规范指 骆驼命名法（也叫驼峰命名法）。
     * 骆驼命名法的意思是：除第一个单词之外，其他单词首字母大写
     * @param name name 的格式是 a_b_c, a/b/c都是单词 eg: hello_beautiful_girl
     * @return 正确的命名
     */
    public boolean isCamelCase(String name) {
        if (isJavaIdentifier(name)) {
            return name.charAt(0) >= 'a' && name.charAt(0) <= 'z';
        } else {
            return false;
        }
    }

    /**
     * 将 name 转换成符合帕斯卡命名规范的标识符名称
     * @param name name 的格式是 a_b_c, a/b/c都是单词 eg: hello_beautiful_girl
     * @return 使用帕斯卡命名的标识符
     */
    public String convertPascal(String name) {
        String[] arr = name.split("_");
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < arr.length; i ++) {
            char a = Character.toUpperCase(arr[i].charAt(0));
            arr[i] = a + arr[i].substring(1);
            str.append(arr[i]);
        }
        return str.toString();
    }

    /**
     * 将 name 转换成符合骆驼命名规范的标识符名称
     * @param name name 的格式是 a_b_c, a/b/c都是单词  eg: hello_beautiful_girl
     * @return 使用骆驼命名的标识符
     */
    public String convertCamelCase(String name) {
        String[] arr = name.split("_");
        StringBuilder str = new StringBuilder();
        for (int i = 1; i < arr.length; i ++) {
            char a = Character.toUpperCase(arr[i].charAt(0));
            arr[i] = a + arr[i].substring(1);
        }
        for (String s : arr) {
            str.append(s);
        }
        return str.toString();
    }
}

